﻿using System;
using EmbeddedSharp.Core;
using EmbeddedSharp.Scripting;
using Zove.Runtime.Core;
using Zove.Runtime.Core.Zoom;

namespace Zove.Scripting.Core {
    public class ZoveScriptingObject : ScriptingObject {

        public ZoveScriptingObject(IContext context)
            : base(context) {
        }

        public ZoveScriptingObject(string source, IContext cntx)
            : base(source, cntx) {
        }

        public ZoveScriptingObject(string source)
            : base(source, new ZoveScriptingContext()) {
        }

        public ZoveScriptingObject()
            : base(new ZoveScriptingContext()) {
            //ZoveDependencyManager.Instance.FunctionManager 
            //    = Context.GetFunctionManager();
        }

        protected override object ProcessInternal(string stmt) {
            if (string.IsNullOrEmpty(stmt.Trim())) {
                return string.Empty;
            }

            Lexer lexer = new Lexer(stmt);
            Token token = lexer.PeekToken(1);
            Token nt = lexer.PeekToken(2);

            if (token.TokenType == TokenType.IDENTIFIER
                && nt.TokenType == TokenType.IDENTIFIER) {
                token = lexer.NextToken();

                string type = token.Value;
                int count = 0;
                do {
                    token = lexer.NextToken();
                    if (token.TokenType == TokenType.Semicolon) {
                        break;
                    } 
                    if (token.TokenType == TokenType.IDENTIFIER) {
                        // add new instances
                        if (Context.HasVariable(nt.Value)) {
                            return String.Format(
                                "Instance {0} was already created.", token.Value);
                        }

                        switch (type) {
                            case "decimal":
                                break;
                            case "string":
                                break;
                            case "list":
                                break;
                            case "var":
                                token = lexer.NextToken();
                                if (token.TokenType == TokenType.Assign) {
                                    // TODO read the next expression instead of a single value here
                                    token = lexer.NextToken();
                                    Context.AddVariable(nt.Value, token.Value);
                                } else {
                                    Context.Assign(nt.Value, 0);
                                }
                                break;
                            default:
                                string instanceName = nt.Value;
                                ZoomLanguageNature languageNature = new ZoomLanguageNature();
                                ClassContentProvider contentProvider = new ClassContentProvider(type, languageNature);
                                ZoveObject instance = new ZoveObject(
                                    instanceName, contentProvider, languageNature);
                                ZoveScriptingContext context = Context as ZoveScriptingContext;
                                if (context == null) {
                                    throw new RuntimeException("Context is not of expected type.");
                                }
                                context.AddInstance(nt.Value, instance);
                                break;
                        }
                        count++;
                    }
                }
                while (lexer.HasMoreTokens());

                string result = string.Format("{0} instance(s) were created.", count);

                return result;
            }

            return base.ProcessInternal(stmt);
        }

        public static IContext Run(string p) {
            string source = System.IO.File.ReadAllText(p);
            ZoveScriptingObject script = new ZoveScriptingObject(source);

            script.Run();

            return script.Context;
        }
    }
}
